package com.xiaoq.sites.endpoint;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.xiaoq.RedisTemplate4JedisCluster;
import com.xiaoq.coms.GenericDataResponse;
import com.xiaoq.coms.util.ConstantUtil;
import com.xiaoq.coms.util.IdGenerator;
import com.xiaoq.coms.util.MathUtil;
import com.xiaoq.qiniu.QiNiuSpaceEnum;
import com.xiaoq.qiniu.UploadUtil;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;

import com.xiaoq.coms.GenericListResponse;
import com.xiaoq.coms.GenericResponse;
import com.xiaoq.sites.entity.SitesPointEntity;
import com.xiaoq.sites.service.ISitesService;
import com.xiaoq.sites.vo.SitesPoint2Vo;

import javax.servlet.http.HttpServletRequest;

@RestController
@RequestMapping("/api/v1")
@Api(tags={"景点相关接口"})
public class SitesPointEndpoint {
	
	private static final class SitePointListResponse extends GenericListResponse<SitesPoint2Vo> {};

	private static final class SitePointDataResponse extends GenericDataResponse<SitesPoint2Vo> {};
	
	private Logger logger = LoggerFactory.getLogger(SitesPointEndpoint.class);
	
	@Autowired
	private ISitesService msSitesApi;
	
	@Autowired
	private IdGenerator idGenerator;

	@Autowired
	private RedisTemplate4JedisCluster redisTemplate;
	
	@ApiOperation(value="景点对接爬虫", notes="景点对接爬虫")
	@ApiResponses({
		@ApiResponse(code = 200, response = GenericResponse.class, message = "景点对接爬虫")
	})
	@PostMapping(value="/sites_point/reptiles", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
	public ResponseEntity<?> reptilesSitesPoint(
			@RequestBody SitesPoint2Vo sitesPointVo){
		String id = sitesPointVo.getId();
		if(StringUtils.isBlank(id)){
			sitesPointVo.setId(idGenerator.nextId());
		}
		String sitesId = sitesPointVo.getSitesId();
		if(StringUtils.isBlank(sitesId)){
			return GenericResponse.ng("景区Id不能缺少");
		}
		String name = sitesPointVo.getName();
		if(StringUtils.isBlank(name)){
			return GenericResponse.ng("景点名称不能缺少");
		}
		String shortName = sitesPointVo.getShortName();
		if(StringUtils.isBlank(shortName)){
			sitesPointVo.setShortName(name);
		}
		Double longitude = sitesPointVo.getLongitude();
		if(longitude==null||longitude==0.0){
			return GenericResponse.ng("景点经度不能缺少");
		}
		Double latitude = sitesPointVo.getLatitude();
		if(latitude==null||latitude==0.0){
			return GenericResponse.ng("景点维度不能缺少");
		}
		int recIndex = sitesPointVo.getRecIndex();
		if(recIndex==0){
			sitesPointVo.setRecIndex(5);
		}
		
		String features = sitesPointVo.getFeatures();
		if(StringUtils.isBlank(features)){
			sitesPointVo.setFeatures("风景秀丽，人文景观良好");
		}
		String detailInfo = sitesPointVo.getDetailInfo();
		if(StringUtils.isBlank(detailInfo)){
			return GenericResponse.ng("景点详情不可缺少");
		}
		
		String mainImgUrl = sitesPointVo.getMainImgUrl();
		if(StringUtils.isBlank(mainImgUrl)){
			return GenericResponse.ng("景点主图不可缺少");
		}
		
		List<String> imgUrls = sitesPointVo.getImgUrls();
		if(imgUrls==null||imgUrls.size()==0){
			return GenericResponse.ng("景点图片列表图不可缺少");
		}
		List<String> tags = sitesPointVo.getTags();
		if(tags==null||tags.size()==0){
			tags = new ArrayList<>();
			tags.add("适合游玩");
			tags.add("费用便宜");
			sitesPointVo.setTags(tags);
		}
		String introduction = sitesPointVo.getIntroduction();
		if(StringUtils.isBlank(introduction)){
			sitesPointVo.setIntroduction(detailInfo);
		}
		SitesPointEntity sitesPointEntity = new SitesPointEntity();
		BeanUtils.copyProperties(sitesPointVo,sitesPointEntity);
		boolean result = msSitesApi.addSitesPoint(sitesPointEntity);
		if(result){
			return GenericResponse.ok();
		}
		return GenericResponse.ng("添加失败");
	}
	
	@ApiOperation(value="(对接运营后端)删除一个景点",notes="(对接运营后端)根据景点Id删除一个景点")
	@ApiResponses({
		@ApiResponse(code=200,response=GenericResponse.class,message="(对接运营后端)删除一个景点")
	})
	@DeleteMapping(value="/sites_point/reptiles",produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
	public ResponseEntity<?> deleteSitesPoint(@RequestParam(value="id",required=true)@ApiParam(value="景点Id",required=true)String id){
		boolean result = msSitesApi.delSitesPoint(id);
		if(result){
			return GenericResponse.ok();
		}
		return GenericResponse.ng("删除失败");
	}
	@ApiOperation(value="(对接运营后端)更新景点", notes="(对接运营后端)更新一个景点")
	@ApiResponses({
		@ApiResponse(code=200,response=GenericResponse.class,message="(对接运营后端)更新一个景点")
	})
	@PutMapping(value="/sites_point/reptiles",produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
	public ResponseEntity<?> updateSitesPoint4OptBack(@RequestBody SitesPoint2Vo sitesPointVo){
		
		SitesPointEntity sitesPointEntity = new SitesPointEntity();
		BeanUtils.copyProperties(sitesPointVo,sitesPointEntity);
		boolean result = msSitesApi.updateSitesPoint(sitesPointEntity);
		if(result){
			return GenericResponse.ok();
		}
		return GenericResponse.ng("更新失败");
	}
	
	@ApiOperation(value="根据景区ID查询景点列表（B端用）", notes="根据景区ID查询景点列表（B端用）")
	@ApiResponses({
		@ApiResponse(code = 200, response = SitePointListResponse.class, message = "根据景区ID查询景点列表（B端用）")
	})
	@GetMapping(value="/sites/sites_point", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
	public ResponseEntity<?> sitesPointList(HttpServletRequest request) {
		String errorMsg = "查询景点列表出错";
		try {

			String userId = (String) request.getAttribute("userId");
			String shopId = redisTemplate.get(ConstantUtil.REDIS_PREFIX_MANAGER_SHOP_RELATION, userId);
			if(StringUtils.isEmpty(shopId)){
				return GenericResponse.ng("管理员没有对应商店");
			}

			List<SitesPointEntity> sitesPointList = msSitesApi.findSitesPointListBySitesId(shopId);
			
			List<SitesPoint2Vo> sitesPointVoList = new ArrayList<>();
			SitesPoint2Vo sitesPointVo = null;
			if(CollectionUtils.isNotEmpty(sitesPointList)) {
				for (SitesPointEntity sitesPoint : sitesPointList) {
					sitesPointVo = new SitesPoint2Vo();
					BeanUtils.copyProperties(sitesPoint, sitesPointVo);
					sitesPointVoList.add(sitesPointVo);
				}
			}
			
			return SitePointListResponse.listNoCount(sitesPointList);
		} catch (Exception e) {
			logger.error(errorMsg,e);
			return GenericResponse.ng(errorMsg);
		}
	}

	@ApiOperation(value="根据景区ID查询景点列表（C端用）", notes="根据景区ID查询景点列表（C端用）")
	@ApiResponses({
			@ApiResponse(code = 200, response = SitePointListResponse.class, message = "根据景区ID查询景点列表（C端用）")
	})
	@GetMapping(value="/sites/{sitesId}/sites_point", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
	public ResponseEntity<?> sitesPointListBySites(@ApiParam(value = "sitesId", required = true)  @PathVariable String sitesId,HttpServletRequest request) {
		String errorMsg = "查询景点列表出错";
		try {

			List<SitesPointEntity> sitesPointList = msSitesApi.findSitesPointListBySitesId(sitesId);

			List<SitesPoint2Vo> sitesPointVoList = new ArrayList<>();
			SitesPoint2Vo sitesPointVo = null;
			if(CollectionUtils.isNotEmpty(sitesPointList)) {
				for (SitesPointEntity sitesPoint : sitesPointList) {
					sitesPointVo = new SitesPoint2Vo();
					BeanUtils.copyProperties(sitesPoint, sitesPointVo);
					sitesPointVoList.add(sitesPointVo);
				}
			}

			return SitePointListResponse.listNoCount(sitesPointList);
		} catch (Exception e) {
			logger.error(errorMsg,e);
			return GenericResponse.ng(errorMsg);
		}
	}
	
	@ApiOperation(value="查询必玩景点列表", notes="查询必玩景点列表")
	@ApiResponses({
			@ApiResponse(code = 200, response = SitePointListResponse.class, message = "查询必玩景点列表")
	})
	@GetMapping(value="/sites/{sitesId}/mplay", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
	public ResponseEntity<?> mPlayPointListBySites(
			@ApiParam(value = "sitesId", required = true)  @PathVariable String sitesId,
			@RequestParam(value="localLongitude",required=false)@ApiParam(value="当前经度",required=false)Double localLongitude,
			@RequestParam(value="localLatitude",required=false)@ApiParam(value="当前纬度",required=false)Double localLatitude
			) {
		String errorMsg = "查询必玩景点列表出错";
		try {

			List<SitesPointEntity> sitesPointList = msSitesApi.findMPlayPointBySitesId(sitesId);
			List<SitesPoint2Vo> sitesPointVoList = new ArrayList<>();
			SitesPoint2Vo sitesPointVo = null;
			if(CollectionUtils.isNotEmpty(sitesPointList)) {
				for (SitesPointEntity sitesPoint : sitesPointList) {
					sitesPointVo = new SitesPoint2Vo();
					BeanUtils.copyProperties(sitesPoint, sitesPointVo);
					if(localLongitude!=null&&localLatitude!=null&&localLongitude!=0.00&&localLatitude!=0.00){
						Double shopLongitude = sitesPointVo.getLongitude();
						Double shopLatitude = sitesPointVo.getLatitude();
						Double distance = MathUtil.distance(localLongitude, localLatitude, shopLongitude, shopLatitude);
						sitesPointVo.setDistance(distance);
						String distanceString = MathUtil.distance(distance);
						sitesPointVo.setDistanceString(distanceString);
					}
					sitesPointVoList.add(sitesPointVo);
				}
			}
			if(sitesPointVoList!=null&&sitesPointVoList.size()>1){
				Collections.sort(sitesPointVoList, new Comparator<SitesPoint2Vo>() {
					
					@Override
					public int compare(SitesPoint2Vo sitesPointVo1, SitesPoint2Vo sitesPointVo2) {
						int status1 = sitesPointVo1.getRecIndex()-sitesPointVo2.getRecIndex();
						if(status1 == 0){
							Double status2 = sitesPointVo1.getDistance()-sitesPointVo2.getDistance();
							if(status2>0){
								return 1;
							}else{
								return -1;
							}
						}else {
							if(status1>0){
								return -1;
							}else{
								return 1;
							}
						}
					}
				});
			}
			return SitePointListResponse.listNoCount(sitesPointVoList);
		} catch (Exception e) {
			logger.error(errorMsg,e);
			return GenericResponse.ng(errorMsg);
		}
	}

	@ApiOperation(value="根据景点ID查询景点（B端用）", notes="根据景点ID查询景点（B端用）")
	@ApiResponses({
			@ApiResponse(code = 200, response = SitePointDataResponse.class, message = "根据景点ID查询景点（B端用）")
	})
	@GetMapping(value="/sites/sites_point/{pointId}", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
	public ResponseEntity<?> getSitesPoint(@ApiParam(value = "pointId", required = true)  @PathVariable String pointId,
												   HttpServletRequest request) {

		String errorMsg = "查询某一景点出错";

		String userId = (String) request.getAttribute("userId");
		String shopId = redisTemplate.get(ConstantUtil.REDIS_PREFIX_MANAGER_SHOP_RELATION, userId);
		if(StringUtils.isEmpty(shopId)){
			return GenericResponse.ng("管理员没有对应商店");
		}

		try {
			SitesPointEntity sitesPointEntity = msSitesApi.findSitesPointByPointId(pointId);
			if(sitesPointEntity == null){
				return GenericResponse.ng(pointId + "，此景点不存在");
			}
			SitesPoint2Vo sitesPointVo = new SitesPoint2Vo();
			BeanUtils.copyProperties(sitesPointEntity, sitesPointVo);
			return SitePointDataResponse.okWithData(sitesPointVo);
		} catch (Exception e) {
			logger.error(errorMsg,e);
			return GenericResponse.ng(errorMsg);
		}
	}
	
	
	@ApiOperation(value="查询景点列表", notes="根据线路ID查询景点列表")
	@ApiResponses({
		@ApiResponse(code = 200, response = SitePointListResponse.class, message = "根据线路ID查询景点列表")
	})
	@GetMapping(value="/route/{routeId}/sites_point", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
	public ResponseEntity<?> sitesPointListByRoutes(
			@PathVariable("routeId") @ApiParam(value = "routeId", required = true) String routeId,
			HttpServletRequest request) {
		String errorMsg = "查询景点列表出错";

		String userId = (String) request.getAttribute("userId");
		String shopId = redisTemplate.get(ConstantUtil.REDIS_PREFIX_MANAGER_SHOP_RELATION, userId);
		if(StringUtils.isEmpty(shopId)){
			return GenericResponse.ng("管理员没有对应商店");
		}

		try {

			List<SitesPointEntity> sitesPointList = msSitesApi.findSitesPointListByRouteId(routeId);
			List<SitesPoint2Vo> sitesPointVoList = new ArrayList<>();
			SitesPoint2Vo sitesPointVo = null;
			if (CollectionUtils.isNotEmpty(sitesPointList)) {
				for (SitesPointEntity sitesPoint : sitesPointList) {
					sitesPointVo = new SitesPoint2Vo();
					BeanUtils.copyProperties(sitesPoint, sitesPointVo);
					sitesPointVoList.add(sitesPointVo);
				}
			}

			return SitePointListResponse.listNoCount(sitesPointList);
		} catch (Exception e) {
			logger.error(errorMsg,e);
			return GenericResponse.ng(errorMsg);
		}
	}


	@ApiOperation(value="添加一个新的景点", notes="景区可以自己添加一个新的景点")
	@ApiResponses({
		@ApiResponse(code = 200, response = GenericResponse.class, message = "条件一个新的景点")
	})
	@PostMapping(value="/sites_point", produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
	public ResponseEntity<?> addSitesPoint(
			@ModelAttribute(value="sitesPointVo")@ApiParam(value="sitesPointVo",required=true)SitesPoint2Vo sitesPointVo,
			@RequestParam(value="file",required=false)@ApiParam(value="主图",required=false)MultipartFile file,HttpServletRequest request){
		String userId = (String) request.getAttribute("userId");
		String shopId = redisTemplate.get(ConstantUtil.REDIS_PREFIX_MANAGER_SHOP_RELATION, userId);
		if(StringUtils.isEmpty(shopId)){
			return GenericResponse.ng("管理员没有对应商店");
		}
		sitesPointVo.setSitesId(shopId);
		if (file != null) {
			String imgUrl = null;
			try {
				imgUrl = UploadUtil.easyUploadByte(file, QiNiuSpaceEnum.XIAOQ_SITES.getName().toLowerCase(),
						QiNiuSpaceEnum.XIAOQ_SITES.getDomain());
				logger.info("景点主图在青牛云上的地址：" + imgUrl);
				if (imgUrl != null) {
					sitesPointVo.setMainImgUrl(imgUrl);;
				}
			} catch (IOException e) {
				logger.error("景点主图上传七牛云出错！", e);
				return GenericResponse.ng("景点主图上传七牛云失败请重新上传！");
			}
		}
		SitesPointEntity sitesPointEntity = new SitesPointEntity();
		BeanUtils.copyProperties(sitesPointVo,sitesPointEntity);
		boolean result = msSitesApi.addSitesPoint(sitesPointEntity);
		if(result){
			return GenericResponse.ok();
		}
		return GenericResponse.ng("景点名称重复！");
	}
	
	@ApiOperation(value="删除一个景点",notes="根据景点Id删除一个景点")
	@ApiResponses({
		@ApiResponse(code=200,response=GenericResponse.class,message="删除一个景点")
	})
	@DeleteMapping(value="/sites_point/{id}",produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
	public ResponseEntity<?> delSitesPoint(@PathVariable(value="id",required=true)@ApiParam(value="id",required=true)String id){
		boolean result = msSitesApi.delSitesPoint(id);
		if(result){
			return GenericResponse.ok();
		}
		return GenericResponse.ng("删除失败");
	}
	@ApiOperation(value="更新景点", notes="更新一个景点")
	@ApiResponses({
		@ApiResponse(code=200,response=GenericResponse.class,message="更新一个景点")
	})
	@PostMapping(value="/sites_point/{id}",produces={MediaType.APPLICATION_JSON_UTF8_VALUE})
	public ResponseEntity<?> updateSitesPoint(
			@ModelAttribute(value="sitesPointVo")@ApiParam(value="sitesPointVo",required=true)SitesPoint2Vo sitesPointVo,
			@RequestParam(value = "file", required = false) @ApiParam(value = "主图", required = false) MultipartFile file,
			@RequestParam(value = "files", required = false) @ApiParam(value = "图片列表", required = false) MultipartFile[] files
			){
		try {
			if (file != null) {
				String imgUrl = null;
				imgUrl = UploadUtil.easyUploadByte(file, QiNiuSpaceEnum.XIAOQ_SITES.getName().toLowerCase(),
						QiNiuSpaceEnum.XIAOQ_SITES.getDomain());
				logger.info("景点主图在青牛云上的地址：" + imgUrl);
				if (imgUrl != null) {
					sitesPointVo.setMainImgUrl(imgUrl);
				}
			}
			if (files != null) {
				List<String> imgUrls = null;
				for (MultipartFile mfile : files) {
					imgUrls = new ArrayList<>();
					String url = UploadUtil.easyUploadByte(mfile,
							QiNiuSpaceEnum.XIAOQ_SITES.getName().toLowerCase(),
							QiNiuSpaceEnum.XIAOQ_SITES.getDomain());
					imgUrls.add(url);

				}
				if (imgUrls != null) {
					sitesPointVo.setImgUrls(imgUrls);
				}
			}
		} catch (IOException e) {
			logger.error("景点辅图列表上传七牛云出错！", e);
			return GenericResponse.ng("景点辅图列表上传七牛云失败请重新上传！");
		}
		SitesPointEntity sitesPointEntity = new SitesPointEntity();
		BeanUtils.copyProperties(sitesPointVo,sitesPointEntity);
		boolean result = msSitesApi.updateSitesPoint(sitesPointEntity);
		if(result){
			return GenericResponse.ok();
		}
		return GenericResponse.ng("更新失败");
	}
	
}